home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
dsp
/
56000tar.z
/
56000tar
/
56000
/
speech
/
adpcmns.asm
< prev
next >
Wrap
Assembly Source File
|
1991-11-26
|
55KB
|
1,556 lines
;
; This program originally available on the Motorola DSP bulletin board.
; It is provided under a DISCLAMER OF WARRANTY available from
; Motorola DSP Operation, 6501 Wm. Cannon Drive W., Austin, Tx., 78735.
;
;**************************************************************************
;
; ADPCMNS.ASM Full-Duplex 32-kbit/s Nonstandard CCITT ADPCM
;
; Version 1.0 - 8/9/90
;
; This program implements the algorithm defined in CCITT Recommendation
; G.721: "32 kbit/s Adaptive Differential Pulse Code Modulation" dated
; August 1986. This code contains a real-time I/O interface for a
; hardware platform consisting of two DSP56000ADS boards, each connected
; to an MC145503 codec.
;
; Please refer to the file ADPCMNS.HLP for further information about
; this program. Also refer to Motorola Application Report APR9/D for
; complete documentation.
;
;**************************************************************************
OPT CC,CEX
START EQU $0020
PBDDR EQU $FFE2
PBD EQU $FFE4
PCC EQU $FFE1
CRA EQU $FFEC
CRB EQU $FFED
SSISR EQU $FFEE
SSIRX EQU $FFEF
SSITX EQU $FFEF
BCR EQU $FFFE
ORG X:$0000
;******************** Encoder variables ***********************************
; I = siii 0000 | 0000 0000 | 0000 0000 (ADPCM format)
I_T DS 1 ;ADPCM codeword
; DQ = siii iiii | iiii iii.f | ffff ffff (24SM)
DQ_T DS 1 ;Quantized difference signal
; Y = 0iii i.fff | ffff ffff | ffff ffff (23SM)
Y_T DS 1 ;Quantizer scale factor
; AP = 0ii.f ffff | ffff ffff | ffff ffff (23SM)
AP_T DS 1 ;Unlimited speed control parameter
; AL = 0i.ff ffff | ffff ffff | ffff ffff (23SM)
AL_T DS 1 ;Limited speed control parameter
;******************** Decoder variables ***********************************
I_R DS 1 ;ADPCM codeword
DQ_R DS 1 ;Quantized difference signal
Y_R DS 1 ;Quantizer scale factor
AP_R DS 1 ;Unlimited speed control parameter
AL_R DS 1 ;Limited speed control parameter
;******************** Temporary variables *********************************
; IMAG = 0000 0000 | 0000 0000 | 0000 0iii.
IMAG DS 1 ;|I|
; PKS1 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
PKS1 DS 1 ;XOR of PK0 & PK1
; PKS2 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
PKS2 DS 1 ;XOR of PK0 & PK2
DATAPTR_T DS 1 ;Transmit data buffer pointer
DATAPTR_R DS 1 ;Receive data buffer pointer
;******************** Table for quantizing DLN ****************************
; Used in QUAN routine
QUANTAB DS 8
;******************** Table for unquantizing I ****************************
; Used in RECONST
IQUANTAB DS 8
;******************** W(I) lookup table ***********************************
; Used in FUNCTW routine
WIBASE DS 8
;******************** F(I) lookup table ***********************************
; Used in FUNCTF routine
FIBASE DS 8
;******************** Table used in COMPRESS ******************************
TAB DS 8
;******************** Encoder data buffer *********************************
; DQ = siii iiii | iiii iiii. | ffff ffff (24TC)
; SRn in same format
DATA_T DSM 8 ;8 word modulo buffer for data,
; R2 is used as pointer, DATAPTR_T
; points to start of buffer (DQ1)
; at beginning of cycle
;******************** Decoder data buffer *********************************
DATA_R DSM 8 ;8 word modulo buffer for data
; (same format as DATA_T)
ORG Y:$0000
;******************** Encoder variables ***********************************
; SE = siii iiii | iiii iiii. | ffff ffff (24TC)
SE_T DS 1 ;Signal estimate
; SEZ = siii iiii | iiii iiii. | ffff ffff (24TC)
SEZ_T DS 1 ;Partial signal estimate
; SR = siii iiii | iiii iiii. | ffff ffff (24TC)
SR_T DS 1 ;Reconstructed signal
; PK0 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
PK0_T DS 1 ;Sign of DQ + SEZ
; PK1 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
PK1_T DS 1 ;Delayed sign of DQ + SEZ
; DMS = 0iii. ffff | ffff ffff | ffff ffff (23SM)
DMS_T DS 1 ;Short term average of F(I)
; DML = 0iii. ffff | ffff ffff | ffff ffff (23SM)
DML_T DS 1 ;Long term average of F(I)
; TDP = i000 0000 | 0000 0000 | 0000 0000 (1TC)
TDP_T DS 1 ;Tone detect
; TD = i000 0000 | 0000 0000 | 0000 0000 (1TC)
TD_T DS 1 ;Delayed tone detect
; YU = 0iii i.fff | ffff ffff | ffff ffff (23SM)
YU_T DS 1 ;Fast quantizer scale factor
; YL = 0iii i.fff | ffff ffff | ffff ffff (23SM)
YL_T DS 1 ;Slow quantizer scale factor
; SIGPK = i000 0000 | 0000 0000 | 0000 0000 (1TC)
SIGPK_T DS 1 ;Sgn[p(k)] flag
; A2P = si.ff ffff | ffff ffff | ffff ffff (24TC)
A2P_T DS 1 ;Second order predictor coef
; TR = i000 0000 | 0000 0000 | 0000 0000 (1TC)
TR_T DS 1 ;Transition detect
; S = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
S_T DS 1 ;Input PCM signal
;******************** Decoder variables ***********************************
SE_R DS 1 ;Signal estimate
SEZ_R DS 1 ;Partial signal estimate
SR_R DS 1 ;Reconstructed signal
PK0_R DS 1 ;Sign of DQ + SEZ
PK1_R DS 1 ;Delayed sign of DQ + SEZ
DMS_R DS 1 ;Short term average of F(I)
DML_R DS 1 ;Long term average of F(I)
TDP_R DS 1 ;Tone detect
TD_R DS 1 ;Delayed tone detect
YU_R DS 1 ;Fast quantizer scale factor
YL_R DS 1 ;Slow quantizer scale factor
SIGPK_R DS 1 ;Sgn[p(k)] flag
A2P_R DS 1 ;Second order predictor coef
TR_R DS 1 ;Transition detect
SP_R DS 1 ;Output PCM signal
;******************** Temporary variables *********************************
DQMAG DS 1 ;|DQ|
SL_T DS 1 ;PCM input for encoder
LAW DS 1 ;PCM mode select
;******************** Shift constant lookup table *************************
; Shift constants used for doing left or right shifts by multiplying by a
; power of 2.
RSHFT DS 24
LSHFT
;******************** Encoder coef. buffer ********************************
; Bn = si.ff ffff | ffff ffff | ffff ffff (24TC)
; An in same format
;8 word modulo buffer for coefs.,
; R6 is used as pointer
COEF_T DSM 8 ;B1
;B2
;B3
;B4
;B5
;B6
;A1
;A2
;******************** Decoder coef. buffer ********************************
;8 locations for coef. queue
; (same format as COEF_T)
COEF_R DSM 8 ;B1
;B2
;B3
;B4
;B5
;B6
;A1
;A2
PAGE
ORG P:$0000
JMP START
ORG P:START
MOVEC #$06,OMR ;Set DE=1
CLR A
MOVEP A,X:BCR ;Set BCR for 0 wait states
JSR INIT
;**************************************************************************
;
; Poll SSI for receiver data available. Note that the SSI transmit and
; receive are synchronous.
;
;**************************************************************************
IOWAIT JCLR #7,X:SSISR,IOWAIT ;Wait for SSIRX full
MOVE Y:SP_R,A ;Get decoder output
MOVEP A,X:SSITX ;Send PCM output to CODEC
MOVEP X:SSIRX,A ;Get input sample
MOVE A,Y:S_T ;Save PCM input for encoder
;**************************************************************************
;
; Encoder
;
;**************************************************************************
ENCODE MOVE X:DATAPTR_T,R2 ;Set data pointer to DQ1EXP
MOVE #COEF_T,R6 ;Set coef pointer to B1
JSR <PRDICT ;(FMULT,ACCUM)
MOVE B,Y:SEZ_T
MOVE A,Y:SE_T
MOVE X:AP_T,A
MOVE Y:YL_T,Y1
MOVE Y:YU_T,Y0
JSR <LIMAMIX ;(LIMA,MIX)
MOVE X1,X:AL_T
MOVE A,X:Y_T
;********************************************
; Get encoder input (PCM data)
MOVE Y:S_T,A
;********************************************
MOVE Y:SE_T,B
MOVE X:Y_T,Y0
JSR <CONVERT ;(EXPAND,SUBTA,LOG,SUBTB,QUAN)
MOVE A,X:I_T
;********************************************
; Output ADPCM word
MOVE A,X1 Y:RSHFT+20,Y0
MPY Y0,X1,A ;Shift ADPCM word to LSB's
MOVEP A1,X:PBD ;Put output on PB0..3
MOVE X:I_T,A
;********************************************
MOVE X:Y_T,B
JSR <IQUAN ;(RECONST,ADDA,ANTILOG)
MOVE A1,X:DQ_T
MOVE Y:TD_T,A
MOVE Y:YL_T,B
JSR <TRANS ;(TRANS)
MOVE A1,Y:TR_T
MOVE Y:SE_T,B
MOVE X:DQ_T,A
MOVE Y:SEZ_T,X0
MOVE #PK1_T,R0
JSR <ADDBC ;(ADDB,ADDC)
MOVE X1,Y:SR_T
MOVE B1,Y:SIGPK_T
MOVE X:DQ_T,Y0
JSR <UPB ;(XOR,UPB)
MOVE Y:SIGPK_T,X0
JSR <UPA2 ;(UPA2,LIMC)
MOVE A,Y:A2P_T
MOVE A,Y:(R6)- ;Save A2P to A2
MOVE Y:SIGPK_T,X1
MOVE Y:A2P_T,X0
JSR <UPA1 ;(UPA1,LIMD)
MOVE X:DQ_T,A
MOVE Y:SR_T,B
JSR <FLOAT ;(FLOATA,FLOATB)
MOVE Y:A2P_T,B
MOVE Y:TR_T,Y0
JSR <TONE ;(TONE,TRIGB)
MOVE Y1,Y:TDP_T
MOVE A,Y:TD_T
MOVE Y:DMS_T,Y0
MOVE Y:DML_T,Y1
JSR <FUNCTF ;(FUNCTF,FILTA,FILTB)
MOVE A,Y:DMS_T
MOVE B,Y:DML_T
MOVE Y:TDP_T,X1
MOVE X:Y_T,Y1
JSR <SUBTC ;(SUBTC)
MOVE X:AP_T,X1
MOVE Y:TR_T,Y1
JSR <FILTC ;(FILTC,TRIGA)
MOVE A1,X:AP_T
MOVE X:Y_T,Y0
MOVE Y:YL_T,Y1
JSR <FUNCTW ;(FUNCTW,FILTD,LIMB,FILTE)
MOVE X0,Y:YU_T
MOVE A1,Y:YL_T
MOVE R2,X:DATAPTR_T ;Save transmit data pointer
;**************************************************************************
;
; Decoder
;
;**************************************************************************
DECODE MOVE X:DATAPTR_R,R2 ;Set data pointer to DQ1EXP
MOVE #COEF_R,R6 ;Set coef pointer to B1
JSR <PRDICT ;(FMULT,ACCUM)
MOVE B,Y:SEZ_R
MOVE A,Y:SE_R
MOVE X:AP_R,A
MOVE Y:YL_R,Y1
MOVE Y:YU_R,Y0
JSR <LIMAMIX ;(LIMA,MIX)
MOVE X1,X:AL_R
MOVE A,X:Y_R
;********************************************
; Get decoder ADPCM input
MOVEP X:PBD,X1
MOVE Y:LSHFT-16,Y0
MPY X1,Y0,A #<$F0,X0 ;Shift to MSB's of A0
MOVE A0,A
AND X0,A ;ADPCM bits in MSB's of A1
MOVE A,X:I_R ;Save decoder input
;********************************************
MOVE X:Y_R,B
JSR <IQUAN ;(RECONST,ADDA,ANTILOG)
MOVE A1,X:DQ_R
MOVE Y:TD_R,A
MOVE Y:YL_R,B
JSR <TRANS ;(TRANS)
MOVE A1,Y:TR_R
MOVE Y:SE_R,B
MOVE X:DQ_R,A
MOVE Y:SEZ_R,X0
MOVE #PK1_R,R0
JSR <ADDBC ;(ADDB,ADDC)
MOVE B1,Y:SIGPK_R
MOVE X1,Y:SR_R
MOVE Y:LAW,B
JSR <COMPRESS ;(COMPRESS)
;********************************************
; Save PCM decoder output (reconstructed signal)
MOVE A1,Y:SP_R
;********************************************
MOVE X:DQ_R,Y0
JSR <UPB ;(XOR,UPB)
MOVE Y:SIGPK_R,X0
JSR <UPA2 ;(UPA2,LIMC)
MOVE A,Y:A2P_R
MOVE A,Y:(R6)-
MOVE Y:SIGPK_R,X1
MOVE Y:A2P_R,X0
JSR <UPA1 ;(UPA1,LIMD)
MOVE X:DQ_R,A
MOVE Y:SR_R,B
JSR <FLOAT ;(FLOATA,FLOATB)
MOVE Y:A2P_R,B
MOVE Y:TR_R,Y0
JSR <TONE ;(TONE,TRIGB)
MOVE Y1,Y:TDP_R
MOVE A,Y:TD_R
MOVE Y:DMS_R,Y0
MOVE Y:DML_R,Y1
JSR <FUNCTF ;(FUNCTF,FILTA,FILTB)
MOVE A,Y:DMS_R
MOVE B,Y:DML_R
MOVE Y:TDP_R,X1
MOVE X:Y_R,Y1
JSR <SUBTC ;(SUBTC)
MOVE X:AP_R,X1
MOVE Y:TR_R,Y1
JSR <FILTC ;(FILTC,TRIGA)
MOVE A1,X:AP_R
MOVE X:Y_R,Y0
MOVE Y:YL_R,Y1
JSR <FUNCTW ;(FUNCTW,FILTD,LIMB,FILTE)
MOVE X0,Y:YU_R
MOVE A1,Y:YL_R
MOVE R2,X:DATAPTR_R
JMP <IOWAIT
;**************************************************************************
; FMULT/ACCUM
;
; Perform adaptive prediction filter using 24-bit fixed point
; multiply and 56-bit accumulate
;
; SEZ(k) = [B1(k-1) * DQ(k-1)] + ... + [B6(k-1) * DQ(k-6)]
; = WB1 + WB2 + ... + WB6
;
; SE(k) = SEZ(k) + [A1(k-1) * SR(k-1)] + [A2(k-1) * SR(k-2)]
; = SEZ + WA1 + WA2
;
; Inputs:
; SRn = X:(R2) = siii iiii | iiii iiii. | ffff ffff (24TC)
; (DQ in same format as SR)
;
; An = Y:(R6) = si.ff ffff | ffff ffff | ffff ffff (24TC)
; (Bn in same format as An)
;
; Outputs:
; SEZ = siii iiii | iiii iiii. | ffff ffff (24TC)
; SE = siii iiii | iiii iiii. | ffff ffff (24TC)
;
;**************************************************************************
PRDICT CLR A X:(R2)+,X0 Y:(R6)+,Y0 ;Get DQ1 & B1
REP #6
MAC X0,Y0,A X:(R2)+,X0 Y:(R6)+,Y0 ;Find SEZ
TFR A,B ;Copy SEZ
ASL B ;Adjust radix pt.
MAC X0,Y0,A X:(R2)+,X0 Y:(R6)+,Y0 ;Accum, get SR2 & A2
MAC X0,Y0,A ;Find SE
ASL A ;Adjust radix pt.
RTS
;**************************************************************************
; LIMA
;
; Limit speed control parameter
;
; AL(k) = 1 if AP(k-1) > 1
; = AP(k-1) if AP(k-1) <= 1
;
; Inputs:
; AP = 0ii.f ffff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; AL = 0i.ff ffff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
LIMAMIX MOVE #<$20,X0 ;Get '1'
CMP X0,A ;Test AP
TGT X0,A ;If AP>'1' set AL='1'
ASL A ;Shift to align radix pt.
;**************************************************************************
; MIX
;
; Form linear combination of fast and slow quantizer
; scale factors
;
; Y(k) = AL(k) * YU(k-1) + [1 - AL(k)] * YL(k-1)
;
; Inputs:
; YL = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; AL = 0i.ff ffff | ffff ffff | ffff ffff (23SM)
; YU = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; Y = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
TFR Y0,A A,X1 ;Swap YU and AL
SUB Y1,A ;Find YU-YL
ABS A A,B ;Find |YU-YL|, save sign
MOVE A,Y0
MPY X1,Y0,A ;Find PRODM=|YU-YL|*AL
NEG A A,X0 ;Find -PRODM, save PRODM
TST B Y1,B ;Check sign
TPL X0,A ;If sign=0 PROD=PRODM,
; else PROD=-PRODM
ADDL B,A ;Find Y=PROD+YL
RTS
;**************************************************************************
; EXPAND
;
; Convert A-law or mu-law PCM to uniform PCM (according to
; Recommendation G.711). For further details see Motorola
; application bulletin "Logarithmic/Linear Conversion
; Routines for DSP56000/1".
;
; Input:
; S = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
;
; Output:
; SL = siii iiii | iiii ii.00 | 0000 0000 (14TC)
;
;**************************************************************************
CONVERT MOVE A,X0 #>$80,Y1 ;Get shift constant
MPY X0,Y1,A #>$7F,X1 ;Shift S to 8 lsb's of A1
AND X1,A ;Mask off sign of S
MOVE A1,N3 ;Load |S| as offset
CMPM Y1,A ;Check sign of S
MOVE X:(R3+N3),A ;Lookup |SL| from ROM table
JGE <SUBTA ;If S=0, SL=|SL|
NEG A ;If S=1, SL=-|SL|
;**************************************************************************
; SUBTA
;
; Compute difference signal by subtracting signal estimate
; from input signal
;
; D(k) = SL(k) - SE(k)
;
; Inputs:
; SL = siii iiii | iiii ii.00 | 0000 0000 (16TC)
; SE = siii iiii | iiii iiii. | ffff ffff (24TC)
;
; Output:
; D = siii iiii | iiii iiii. | ffff ffff (24TC)
;**************************************************************************
SUBTA ASR A ;Sign extend SL and
SUBR B,A ; find D=SL-SE
;**************************************************************************
; LOG
;
; Convert difference signal from the linear to the log
; domain. Use approximation LOG2[1 + x] = x
;
; Input:
; D = siii iiii | iiii iiii. | ffff ffff (24TC)
;
; Outputs:
; DL = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; DS = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
;
;**************************************************************************
ABS A A,Y1 ;Find DQM=|D|, save DS to Y1
MOVE Y:RSHFT+15,X0 ;Get '1'
CMP X0,A #<$40,X1 ;Check for DQM<1
JGE <NORMEXP
CLR A ;If DQM<1 set DL=0
JMP <SUBTB ; and continue
NORMEXP
MOVE #$000E,R0 ;Get exp bias (14)
REP #14 ;If DQM!=0, do norm iteration
NORM R0,A ; 14 times to find MSB of DQM
EOR X1,A Y:LSHFT-19,X0 ;Zero MSB of MANT, get EXP shift
MOVE R0,X1 ;Move EXP to X1
MPY X0,X1,A A,X1 ;Shift EXP<<19, save MANT to X1
MOVE Y:RSHFT+3,X0 ;Get shift
MOVE A0,A ;Move EXP to A1
MAC X0,X1,A ;Shift MANT>>3 & combine with EXP
;**************************************************************************
; SUBTB
;
; Scale log version of difference signal by subtracting
; scale factor
;
; DLN(k) = DL(k) - Y(k)
;
; Inputs:
; DL = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; Y = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
; Output:
; DLN = siii i.fff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
SUBTB SUB Y0,A ;Find DLN=DL-Y
;**************************************************************************
; QUAN
;
; Quantize difference signal in log domain
;
; log2|D(k)| - Y(k) | |I(k)|
; ------------------+--------
; [3.12, + inf) | 7
; [2.72, 3.12) | 6
; [2.34, 2.72) | 5
; [1.91, 2.34) | 4
; [1.38, 1.91) | 3
; [0.62, 1.38) | 2
; [-0.98, 0.62) | 1
; (- inf, -0.98) | 0
;
; Inputs:
; DLN = siii i.fff | ffff ffff | ffff ffff (24TC)
; DS = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
;
; Output:
; I = siii 0000 | 0000 0000 | 0000 0000 (ADPCM format)
;
;**************************************************************************
MOVE #QUANTAB,R0 ;Get quantization table base
MOVE #>QUANTAB+2,X1 ;Get offset for quan conversion
MOVE X:(R0)+,X0 ;Get quan table value
TSTDLN CMP X0,A X:(R0)+,X0 ;Compare to DLN
JGE <TSTDLN ;If value<DLN try next range
MOVE R0,A ;When range found...
; subtract pointer from
SUB X1,A Y:LSHFT-20,X0 ; base to get IMAG=|I|
MOVE A1,X1
MPY X0,X1,A Y1,B ;Shift IMAG <<20, result is
; in A0, move DS (from LOG) into B
MOVE A0,A
TST A #<$F0,X0 ;Check IMAG, get invert mask
JEQ <INVERT ;If IMAG=0 invert bits
TST B ;If IMAG!=0, check DS
JPL <IOUT ;If DS=1 don't invert IMAG
INVERT EOR X0,A ;If DS=0 or IMAG=0 invert IMAG
IOUT MOVE A1,A ;Adjust sign extension
RTS
;**************************************************************************
; RECONST
;
; Reconstruct quantized difference signal in the log domain
;
; |I(k)| | log2|DQ(k)| - Y(k)
; --------+-------------------
; 7 | 3.32
; 6 | 2.91
; 5 | 2.52
; 4 | 2.13
; 3 | 1.66
; 2 | 1.05
; 1 | 0.031
; 0 | - inf
;
; Inputs:
; I = iiii 0000 | 0000 0000 | 0000 0000 (ADPCM format)
;
; Output:
; DQLN = siii i.fff | ffff 0000 | 0000 0000 (12TC)
; DQS = sXXX 0000 | 0000 0000 | 0000 0000 (1TC)
; IMAG = 0000 0000 | 0000 0000 | 0000 0iii.
;
;**************************************************************************
IQUAN MOVE A,Y1 ;Save DQS (sign of I) to Y1
MOVE #<$F0,X1
EOR X1,A Y:RSHFT+20,Y0 ;Invert bits of I
TMI Y1,A ;If ^IS=1, use I, else use ^I
MOVE A1,X0
MPY X0,Y0,A #IQUANTAB,R0 ;Shift IMAG>>20
MOVE A1,N0 ;Load IMAG as offset into IQUAN table
MOVE A1,X:IMAG ;Save |I|
MOVE X:(R0+N0),A ;Lookup DQLN
;**************************************************************************
; ADDA
;
; Add scale factor to log version of quantized difference
; signal
;
; DQL(k) = DQLN(k) + Y(k)
;
; Inputs:
; Y = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; DQLN = siii i.fff | ffff 0000 | 0000 0000 (12TC)
;
; Output:
; DQL = siii i.fff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
ADD B,A ;Find DQL=DQLN+Y
;**************************************************************************
; ANTILOG
;
; Convert quantized difference signal from log to linear
; domain. Use approximation 2**(x) = 1 + x
;
; Input:
; DQL = siii i.fff | ffff ffff | ffff ffff (24TC)
; DQS = sXXX 0000 | 0000 0000 | 0000 0000 (1TC)
;
; Outputs:
; DQ = siii iiii | iiii iii.f | ffff ffff (24SM)
;
;**************************************************************************
JPL <CONVLOG ;If DQL>=0 convert DQL,
; else DQL<0, set |DQ|=0
TFR Y1,A #<$80,X0 ;Get DQS (MSB of I), get mask
AND X0,A #0,B ;Mask off DQS, set |DQ|=0
MOVE B1,Y:DQMAG ;Save DQMAG=|DQ|
JMP <SAVEDQ
CONVLOG
TFR A,B #$07FFFF,X0 ;Get mask
AND X0,A #<$08,X1 ;Find fractional part (DMN), get '1'
OR X1,A #<$78,X0 ;Add '1' to DMN to find DQT,
; get integer mask
AND X0,B Y:RSHFT+19,Y0 ;Find integer part (DEX),
; get shift constant
MOVE B1,X0
MPY X0,Y0,B #>$0A,X0 ;Shift DEX>>19, get '10'
SUB X0,B #$7FFFFF,X0 ;Find DQT shift=DEX-10
JEQ <TRUNCDQM ;If DEX=10, no shift
JLT <SHFRDQ ;If DEX<10, shift right
REP B1 ;Else shift DQT left
LSL A ; up to 4 times
JMP <TRUNCDQM
SHFRDQ NEG B #RSHFT,R0 ;Find 10-DEX
MOVE B1,N0 ;Use 10-DEX for shift lookup
MOVE A1,Y0
MOVE Y:(R0+N0),X1 ;Lookup shift constant
MPY X1,Y0,A ;Shift DQT right up to 9 times
TRUNCDQM AND X0,A #<$80,B ;Truncate to find DQMAG=|DQ|,
; get sign mask
AND Y1,B A1,Y:DQMAG ;Mask off DQS, save DQMAG
MOVE B1,X0
OR X0,A ;Add DQS to DQMAG to get DQ
;Note: result in A1, not A
SAVEDQ RTS
;**************************************************************************
; TRANS
;
; Transition detector
;
; TR(k) = 1 if TD(k)=1 and |DQ(k)|> 24 x 2**(YL(k))
; 0 otherwise
;
; Inputs:
; TD = i000 0000 | 0000 0000 | 0000 0000 (1TC)
; YL = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; DQ = siii iiii | iiii iii.f | ffff ffff (24SM)
;
; Output:
; TR = i000 0000 | 0000 0000 | 0000 0000 (1TC)
;
;**************************************************************************
TRANS TST A #0,A ;Check TD, set TR=0
JEQ <SAVETR ;If TD=0 save TR=0
; else test DQ and YL
TFR B,A #$07FFFF,X0 ;Save YL, get mask
AND X0,A #<$08,X0 ;Find YLFRAC (YL>>10), get '1'
OR X0,A B,X1 ;Add implied '1' to YLFRAC,
MOVE Y:RSHFT+19,Y1 ;Get shift const
MPY Y1,X1,B #>$08,X0 ;Find YLINT=YL>>19, get '8'
MOVE B1,B ;Clear fractional portion
CMP X0,B #>$05,X0 ;Compare YLINT to '8', get '5'
JGT <MAXTHR ;If YLINT>8 set maximum THR2
SUB X0,B ;Find YLINT-5
JEQ <SETDQTHR ;If YLINT=5 don't shift
JLT <RSHIFT ;If YLINT<5 shift right
REP B1 ;Else shift YLFRAC left
LSL A ; up to 3 times to get THR1
JMP <SETDQTHR
MAXTHR MOVE #<$7C,A ;Set maximum THR1
JMP <SETDQTHR
RSHIFT NEG B #RSHFT,R0 ;Find 5-YLINT
MOVE B1,N0 ;Use 5-YLINT for shift lookup
MOVE A1,X0
MOVE Y:(R0+N0),X1 ;Lookup shift constant
MPY X0,X1,A ;Shift YLFRAC right up to 5 times
; to get THR1
SETDQTHR TFR A,B ;Copy THR1=2**(YL)
ADDR B,A #0,X1
ASR A Y:DQMAG,X0 ;Find DQTHR='24' x 2**(YL)
CMP X0,A #<$80,A ;Compare DQMAG to DQTHR, set TR=1
TGT X1,A ;If DQMAG>DQTHR leave TR=1,
; else DQMAG<=DQTHR, set TR=0
SAVETR RTS
;**************************************************************************
; ADDB
;
; Add quantized difference signal and signal estimate
; to form reconstructed signal
;
; SR(k-n) = SE(k-n) + DQ(k-n)
;
; Inputs:
; DQ = siii iiii | iiii iii.f | ffff ffff (24SM)
; SE = siii iiii | iiii iiii. | ffff ffff (24TC)
;
; Output:
; SR = siii iiii | iiii iiii. | ffff ffff (24TC)
;
;**************************************************************************
ADDBC TST A Y:DQMAG,A ;Check DQS, get DQMAG
JPL <SHFTDQ ;If DQS=0 continue
NEG A ;Convert DQ to 2's comp
SHFTDQ ADDR B,A A,B ;Find SR=DQ+SE, save DQ
TFR B,A A,X1 ;Swap DQ and SR
;**************************************************************************
; ADDC
;
; Obtain sign of addition of the quantized difference
; signal and the partial signal estimate
;
; P(k) = DQ(k) + SEZ(k)
; PK0 = sign of P(k)
;
; Inputs:
; DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
; SEZ = siii iiii | iiii iiii. | ffff ffff (24TC)
;
; Output:
; PK0 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
; SIGPK = i000 0000 | 0000 0000 | 0000 0000 (1TC)
;
;**************************************************************************
ADD X0,A #0,B ;Find DQSEZ=DQ+SEZ,
; set SIGPK=0
TST A #<$80,X0 ;Check DQSEZ, get '1'
TEQ X0,B ;If DQSEZ=0, SIGPK=1,
; else SIGPK=0
MOVE Y:(R0)-,Y1 ;Get PK1
MOVE Y:(R0)+,X0 ;Get PK0
MOVE X0,Y:(R0)- ;Delay previous PK0
EOR X0,A A1,Y:(R0) ;Save new PK0, find PKS1=PK0**PK1
; for UPA1 & UPA2
MOVE A1,X:PKS1 ;Save PKS1
MOVE Y:(R0),A
EOR Y1,A ;Find PKS2=PK0**PK2 for UPA2
MOVE A1,X:PKS2 ;Save PKS2
RTS
;**************************************************************************
; XOR/UPB
;
; Update the coefficients of the sixth order predictor
;
; Bn(k) = [1-(2**-8)] * Bn(k-1)
; + (2**-7) * sgn[DQ(k)] * sgn[DQ(k-n)]
; Un = sgn[DQ(k)] XOR sgn[DQ(k-n)]
;
; Inputs:
; Bn = Y:(R6+n) = si.ff ffff | ffff ffff | ffff ffff (24TC)
; DQ = siii iiii | iiii iii.f | ffff ffff (24SM)
;
; Outputs:
; BnP = Y:(R6+n) = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
UPB MOVE Y:DQMAG,B
MOVE #$008000,X0 ;Get +gain
DO #6,ENDUPB ;Do UPB and XOR for B1-B6
MOVE X:(R2)+,A Y:(R6),Y1 ;Get Bn & DQnS
EOR Y0,A #$FF8000,X1 ;Find Un=DQS**DQnS (XOR),
; get -gain
TPL X0,A ;If Un=0 set UGBn=+gain
TMI X1,A ;If Un=1 set UGBn=-gain
TST B #0,X1 ;Test for |DQ|=0
TEQ X1,A ;If |DQ|=0, Then UGBn=0
MOVE Y:RSHFT+8,X1 ;Get shift constant
MAC -X1,Y1,A ;Find UBn=UGBn-(Bn>>8)
ADD Y1,A ;Find BnP=Bn+UBn
MOVE A1,Y:(R6)+ ;Store BnP to Bn
ENDUPB RTS
;**************************************************************************
; UPA2
;
; Update the A2 coefficient of the second order predictor.
;
; A2(k) = [1-(2**-7)] * A2(k-1)
; + (2**-7) * { sgn[P(k)] * sgn[P(k-2)]
; - F[A1(k-1)] * sgn[P(k)] * sgn[P(k-1)] }
;
; F[A1(k)] = 4 * A1 if |A1|<=(2**-1)
; = 2 * sgn(A1) if |A1|>(2**-1)
;
; Inputs:
; A1 = Y:(R6) = si.ff ffff | ffff ffff | ffff ffff (24TC)
; A2 = Y:(R6+1) = si.ff ffff | ffff ffff | ffff ffff (24TC)
; SIGPK = i000 0000 | 0000 0000 | 0000 0000 (1TC)
; PK0 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
; PK1 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
; PK2 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
; (Note: PKS1 & PKS2 have been previously calculated)
;
; Outputs:
; A2T = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
UPA2 MOVE X:PKS2,A ;Get PKS2=PK0**PK2
MOVE #<$10,Y0 ;Get '+1'
TST A #<$F0,Y1 ;Check PKS2, get '-1'
TPL Y0,A ;If PKS2=0, set UGA2A='+1'
TMI Y1,A ;If PKS2=1, set UGA2A='-1'
MOVE A,X1 Y:(R6)+,A ;Save UGA2A, get A1
MOVE #$1FFF00,Y0 ;Get '+1.99'
CMP Y0,A #$E00100,Y1 ;Check A1, get '-1.99'
TGT Y0,A ;If A1>=1/2, set FA1='1.99'
CMP Y1,A X:PKS1,B ;Check A1 again, get PKS1=PK0**PK1
TLT Y1,A ;If A1<=-1/2, set FA1='-1.99'
TST B ;Check PKS1
JMI <FINDSUM ;If PKS1=1, FA=FA1
NEG A ; else PKS1=0, set FA=-FA1
FINDSUM ADD X1,A Y:RSHFT+5,Y1 ;Find UGA2B=UGA2A+FA
TFR X0,B A,X1
MPY X1,Y1,A #0,X0 ;Find UGA2B>>7
TST B Y:(R6),Y0 ;Check SIGPK, get A2
TMI X0,A ;If SIGPK=1, set UGA2=0
MOVE Y:RSHFT+7,X0 ;Get shift constant
MAC -Y0,X0,A ;Find UA2=UGA2-(A2>>7)
ADD Y0,A ;Find A2T=A2+UA2
;**************************************************************************
; LIMC
;
; Limit the A2 coefficient of the second order predictor.
;
; |A2(k)| <= '0.75'
;
; Inputs:
; A2T = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
; Outputs:
; A2P = Y:(R6) = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
MOVE #<$D0,X0 ;Get A2LL
CMP X0,A #<$30,X1 ;Check A2P, get A2UL
TLT X0,A ;If A2P<-0.75, set A2P=-0.75
CMP X1,A ;Check A2P again
TGT X1,A ;If A2P>0.75, set A2P=0.75
RTS
;**************************************************************************
; UPA1
;
; Update the A1 coefficient of the second order predictor.
;
; A1(k) = [1-(2**-8)] * A1(k-1)
; + 3 * (2**-8) * sgn[P(k)] * sgn[P(k-1)]
;
; Inputs:
; A1 = Y:(R6) = si.ff ffff | ffff ffff | ffff ffff (24TC)
; SIGPK = Y:(R0) = i000 0000 | 0000 0000 | 0000 0000 (1TC)
; PK0 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
; PK1 = sXXX XXXX | XXXX XXXX | XXXX XXXX (1TC)
; (Note: PKS1 has been previously calculated)
;
; Outputs:
; A1T = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
UPA1 MOVE #$00C000,Y0 ;Get +gain
MOVE X:PKS1,B ;Get PKS1=PK0**PK1
TST B #$FF4000,Y1 ;Check PKS1, get -gain
TPL Y0,A ;If PKS=0, set UGA1=+gain
TMI Y1,A ;If PKS=1, set UGA1=-gain
MOVE X1,B
TST B #0,X1 ;Check SIGPK
TMI X1,A ;If SIGPK=1, set UGA1=0
MOVE Y:(R6),X1 ;Get A1
MOVE Y:RSHFT+8,Y0 ;Get shift constant
MAC -Y0,X1,A ;Find UA1=UGA1-(A1>>8)
ADD X1,A ;Find A1T=A1+UA1
;**************************************************************************
; LIMD
;
; Limit the A1 coefficient of the second order predictor.
;
; |A1(k)| <= [1-(2**-4)] - A2(k)
;
; Inputs:
; A1T = si.ff ffff | ffff ffff | ffff ffff (24TC)
; A2P = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
; Outputs:
; A1P = Y:(R6) = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
;**************************************************************************
MOVE #<$3C,B ;Get OME='1-(2**-4)'
SUB X0,B ;Find A1UL=OME-A2P
CMP B,A B,X0 ;Check A1T
TGT X0,A ;If A1T>A1UL, set A1P=A1UL
NEG B #2,N6 ;Find A1LL=-A1UL=A2P-OME
CMP B,A B,X0 ;Check A1T again
TLT X0,A ;If A1T<A1LL, set A1P=A1LL
MOVE A1,Y:(R6)+N6 ;Store A1P to A1
RTS
;**************************************************************************
; FLOATA
;
; Convert the quantized difference signal from signed magnitude
; to two's complement and save to the data buffer.
;
; Inputs:
; DQ = siii iiii | iiii iii.f | ffff ffff (24SM)
;
; Outputs:
; DQ = X:(R2) = siii iiii | iiii iiii. | ffff ffff (24TC)
;
;**************************************************************************
FLOAT TST A #2,N2 ;Test sign of DQ
JPL <TRUNCDQ
MOVE Y:DQMAG,A ;If DQ<0,
NEG A ; negate magnitude of DQ
TRUNCDQ ASR A (R2)+ ;Sign extend to 16TC
MOVE A,X:(R2)-N2
;**************************************************************************
; FLOATB
;
; Save the reconstructed signal to the data buffer.
;
; Inputs:
; SR = siii iiii | iiii iiii. | ffff ffff (24TC)
;
; Outputs:
; SR = X:(R2) = siii iiii | iiii iiii. | ffff ffff (24TC)
;
;**************************************************************************
MOVE B,X:(R2)+N2
RTS
;**************************************************************************
; TONE
;
; Partial band signal detection
;
; TD(k) = 1 if A2(k) < -0.71875
; 0 otherwise
;
; Inputs:
; A2P = si.ff ffff | ffff ffff | ffff ffff (24TC)
;
; Output:
; TDP = i000 0000 | 0000 0000 | 0000 0000 (1TC)
;
;**************************************************************************
TONE CLR A #<$D2,X0 ;Get '-.71875', set TDP=0
CMP X0,B #<$80,X1 ;Check A2P, get '1'
TLT X1,A ;If A2P<-.71875 set TDP=1, else TDP=0
;**************************************************************************
; TRIGB
;
; Predictor trigger block
;
; If TR(k) = 1, An(k)=Bn(k)=TD(k)=0
;
; Inputs:
; TR = i000 0000 | 0000 0000 | 0000 0000 (1TC)
; BnP = si.ff ffff | ffff ffff | ffff ffff (24TC)
; AnP = si.ff ffff | ffff ffff | ffff ffff (24TC)
; TDP = i000 0000 | 0000 0000 | 0000 0000 (1TC)
;
; Output:
; BnR = si.ff ffff | ffff ffff | ffff ffff (24TC)
; AnR = si.ff ffff | ffff ffff | ffff ffff (24TC)
; TDR = i000 0000 | 0000 0000 | 0000 0000 (1TC)
;
;**************************************************************************
MOVE Y0,B
TST B A,Y1 ;Test TR
JEQ <ENDTRIG
CLR A ;If TR=1, set TDR=0,
REP #8 ; and B1-B6,A1,A2=0
MOVE A,Y:(R6)+
ENDTRIG RTS
;**************************************************************************
; FUNCTF
;
; Maps quantizer output I into F(I) function
;
; |I(k)| | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
; ---------+---+---+---+---+---+---+---+---+
; F[I(k)] | 7 | 3 | 1 | 1 | 1 | 0 | 0 | 0 |
;
; Inputs:
; I = siii. 0000 | 0000 0000 | 0000 0000
;
; Output:
; FI = 0iii. 0000 | 0000 0000 | 0000 0000 (3SM)
;
;**************************************************************************
FUNCTF MOVE #FIBASE,R0 ;Load lookup table base
MOVE X:IMAG,N0 ;Load IMAG as offset
NOP
MOVE X:(R0+N0),A ;Get FI from lookup table
;**************************************************************************
; FILTA
;
; Update short term average of F(I)
;
; DMS(k) = (1 - 2**(-5)) * DMS(k-1) + 2**(-5) * F[I(k)]
;
; Inputs:
; FI = 0iii. 0000 | 0000 0000 | 0000 0000 (3SM)
; DMS = 0iii. ffff | ffff ffff | ffff ffff (23SM)
;
; Output:
; DMSP = 0iii. ffff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
SUB Y0,A A,B ;Find DIF=FI-DMS, save FI
TFR Y0,A A,X0 ;Move DIF and DMS
MOVE Y:RSHFT+5,X1 ;Get mask
MAC X0,X1,A ;Find DMSP=(DIF>>5)+DMS
;**************************************************************************
; FILTB
;
; Update long term average of F(I)
;
; DML(k) = (1 - 2**(-7)) * DML(k-1) + 2**(-7) * F[I(k)]
;
; Inputs:
; FI = 0iii. 0000 | 0000 0000 | 0000 0000 (3SM)
; DML = 0iii. ffff | ffff ffff | ffff ffff (23SM)
;
; Output:
; DMLP = 0iii. ffff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
SUB Y1,B Y:RSHFT+7,X1 ;Find DIF=FI-DML
TFR Y1,B B,X0
MAC X0,X1,B ;Find DMLP=(DIF>>7)+DML
RTS
;**************************************************************************
; SUBTC
;
; Compute magnitude of the difference of short and long
; term functions of quantizer output sequence and then
; perform threshold comparison for quantizing speed control
; parameter.
;
; AX = 1 if Y(k)>=3, TD(k)=1, & |DMS(k)-DML(k)|>(2**-3)*DML(k)
; = 0 otherwise
;
; Input:
; Y = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; DMSP = 0iii. ffff | ffff ffff | ffff ffff (23SM)
; DMLP = 0iii. ffff | ffff ffff | ffff ffff (23SM)
; TDP = i000 0000 | 0000 0000 | 0000 0000 (1TC)
;
; Output:
; AX = 0i0.0 0000 | 0000 0000 | 0000 0000 (1SM)
;
;**************************************************************************
SUBTC SUB B,A Y:RSHFT+3,X0 ;Find DIF=DMSP-DMLP
ABS A B,Y0 ;Find DIFM=|DIF|
MPY X0,Y0,B #<$40,X0 ;Find DTHR=DMLP>>3, get '1'
CMP B,A #0,B ;Compare DIFM & DTHR, set AX=0
TGE X0,B ;If DIFM>=DTHR set AX=1
MOVE X1,A ;Get TDP
TST A #<$18,Y0 ;Check TDP, get '3'
TNE X0,B ;If TDP!=0 set AX=1
MOVE Y1,A
CMP Y0,A ;Check for Y<"3"
TLT X0,B ;If Y<"3" set AX=1
RTS
;**************************************************************************
; FILTC
;
; Low pass filter of speed control parameter
;
; AP(k) = (1-2**(-4)) * AP(k-1) + AX
;
; Inputs:
; AX = 0i0.0 0000 | 0000 0000 | 0000 0000 (1SM)
; AP = 0ii.f ffff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; APP = 0ii.f ffff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
FILTC SUB X1,B Y:RSHFT+4,Y0 ;Find DIF=AX-AP
TFR X1,A B,X0
MAC X0,Y0,A ;Find APP=(DIF>>4)+AP
;**************************************************************************
; TRIGA
;
; Speed control trigger block
;
; AP(k) = AP(k) if TR(k)=0
; = 1 if TR(k)=1
;
; Inputs:
; TR = i000 0000 | 0000 0000 | 0000 0000 (1TC)
; APP = 0ii.f ffff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; APR = 0ii.f ffff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
MOVE Y1,B
TST B #<$20,X0 ;Check TR, get '1'
TMI X0,A ;If TR=1 set APR=1, else APR=APP
RTS
;**************************************************************************
; FUNCTW
;
; Map quantizer output into logarithmic version of scale
; factor multiplier
;
; |I(k)| | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
; ---------+-----+-----+-----+-----+-----+-----+-----+-----+
; W(I) |70.13|22.19|12.38| 7.00| 4.00| 2.56| 1.13|-0.75|
;
; Inputs:
; I = siii. 0000 | 0000 0000 | 0000 0000
;
; Outputs:
; WI = siii iiii. | ffff 0000 | 0000 0000 (12TC)
;
;**************************************************************************
FUNCTW MOVE #WIBASE,R0 ;Load lookup table base
MOVE X:IMAG,N0 ;Load IMAG as offset
NOP
MOVE X:(R0+N0),A ;Get WI from lookup table
;**************************************************************************
; FILTD
;
; Update of fast quantizer scale factor
;
; YU(k) = (1 - 2**(-5)) * Y(k) + 2**(-5) * W[I(k)]
;
; Inputs:
; WI = siii iiii. | ffff 0000 | 0000 0000 (12TC)
; Y = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; YUT = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
MOVE Y:RSHFT+3,X1 ;Get shift constant
MAC -Y0,X1,A Y0,B ;Find DIF=WI-(Y>>3)
ASR A
ADDR B,A ;Find YUT=(DIF>>5)+Y (actually DIF>>2)
;**************************************************************************
; LIMB
;
; Limit quantizer scale factor
;
; 1.06 <= YU(k) <= 10.00
;
; Inputs:
; YUT = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; YUP = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
MOVE #<$50,X0 ;Get upper limit '10'
CMP X0,A #$088000,X1 ;Check for YU>10,
; get lower limit '1.06'
TGT X0,A ;If YU>10 set YU=10
CMP X1,A ;Check for YU<1.06
TLT X1,A ;If YU<1.06 set YU=1.06
MOVE A,X0 ;Save YUP
;**************************************************************************
; FILTE
;
; Update of slow quantizer scale factor
;
; YL(k) = (1 - 2**(-6)) * YL(k-1) + 2**(-6) * YU(k)
;
; Inputs:
; YUP = 0iii i.fff | ffff ffff | ffff ffff (23SM)
; YL = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
; Outputs:
; YLP = 0iii i.fff | ffff ffff | ffff ffff (23SM)
;
;**************************************************************************
MOVE Y1,B
SUB B,A Y:RSHFT+6,Y0 ;Find DIF=YUP-YL
TFR B,A A,X1
MAC Y0,X1,A ;Find YLP=(DIFSX>>6)+YL
RTS
;**************************************************************************
; COMPRESS
;
; Convert from uniform PCM to A-law or mu-law PCM (according to
; Recommendation G.711). For further details see Motorola
; application bulletin "Logarithmic/Linear Conversion
; Routines for DSP56000/1".
;
; Input:
; SR = siii iiii | iiii iiii. | 0000 0000 (16TC)
;
; Output:
; SP = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
;
;**************************************************************************
COMPRESS
MOVE #$002100,Y0 ;Get bias
TST B X1,A
JNE <ALAW
; Linear to log routine for mu-law
ABS A A,B ;Find |SR|, save sign
ADD Y0,A ;Add bias
ASL A #TAB+7,R0 ;Shift << 2, get seg ptr
ASL A X:TAB+3,X0 ; and get max. word
TES X0,A ;If overflow in extension
; set the maximum PCM word
REP #7 ;Find MSB of data
NORM R0,A
ASL A #<$20,Y0
LSL B A1,X0
MPY X0,Y0,A X:(R0),X1
AND X1,A
ROR A
NOT A #<$FF,X0
AND X0,A
MOVE A1,A
JMP <SAVESP
; Linear to log routine for A-law
ALAW MOVE #$FFFF00,X0
AND X0,A
ABS A A,B ;Find |SR|, save sign
TST B #$000100,X0
JPL <NOSUB
SUB X0,A
NOSUB MOVE #$7FFE00,X0
AND X0,A
ASL A #TAB+7,R0 ;Shift << 2, get seg ptr
ASL A X:TAB+3,X0 ; and get max. word
TES X0,A ;If overflow in extension
; set the maximum PCM word
REP #6 ;Find MSB of data
NORM R0,A
JNR <SEGOK
MOVE (R0)-
SEGOK LSL A #<$20,Y0
LSL B A1,X0
MPY X0,Y0,A X:(R0),X1
AND X1,A
ROR A #<$D5,Y1
EOR Y1,A #<$FF,X0 ;Invert even bits & sign
AND X0,A
MOVE A1,A
SAVESP RTS
;**************************************************************************
; INIT
;
; Initialize program variables, transfer data tables to X and Y
; memory, and set up registers
;
;**************************************************************************
INIT MOVE A,R0
REP #$7F ;Clear internal data RAM
MOVE A,L:(R0)+
; X memory initialization
MOVE #DATA_T,A0 ;Set transmit data pointer
MOVE A0,X:DATAPTR_T ; to start of transmit data buffer
MOVE #DATA_R,A0 ;Set receive data pointer
MOVE A0,X:DATAPTR_R ; to start of receive data buffer
MOVE #$3E2000,X0
MOVE X0,X:AP_T ;Initialize speed control parameters
MOVE X0,X:AP_R
MOVE #VARINIT,R0 ;Copy constant tables into
MOVE #QUANTAB,R3 ; X memory
DO #40,XTABLES
MOVE P:(R0)+,X0
MOVE X0,X:(R3)+
XTABLES
; Y memory initialization
MOVE #$088000,X0
MOVE X0,Y:YU_T ;Initialize quantizer scale factors
MOVE X0,Y:YL_T
MOVE X0,Y:YU_R
MOVE X0,Y:YL_R
MOVE #RSHFT,R3 ;Copy shift constant table into
DO #24,YTABLES ; Y memory
MOVE P:(R0)+,X0
MOVE X0,Y:(R3)+
YTABLES
MOVEC #7,M2 ;Set data buffer for mod(7)
MOVEC #7,M6 ;Set coef buffer for mod(7)
MOVEC #$7F,M3 ;Set PCM table for mod(127)
MOVE #0,A ;Select mu-law or A-law,
MOVE A,Y:LAW ; for mu-law set LAW=0 (default),
; for A-law set LAW!=0
TST A #$100,R3 ;If LAW=0 select mu-law table
JEQ <IOINIT ; base (in X ROM), otherwise
MOVE #$180,R3 ; select A-law table base
IOINIT MOVEP #$00000F,X:PBD ;Initialize PB0..3
MOVEP #$00000F,X:PBDDR ;Set PB0..3 for outputs
MOVEP #$003200,X:CRB ;Set up SSI mode
MOVEP #$000000,X:CRA ;Set up SSI rate
MOVEP #$0001E0,X:PCC ;Enable SSI output pins
MOVEP #0,X:SSITX ;Dummy write to SSI transmitter
RTS
; QUANTAB
VARINIT DC $F84000 ;-0.98
DC $050000 ;0.62
DC $0B2000 ;1.38
DC $0F6000 ;1.91
DC $12C000 ;2.34
DC $15D000 ;2.72
DC $190000 ;3.12
DC $7FFFFF ;15.99
; IQUANTAB
DC $800000 ;-16 |I|=0
DC $004000 ;0.031 |I|=1
DC $087000 ;1.05 |I|=2
DC $0D5000 ;1.66 |I|=3
DC $111000 ;2.13 |I|=4
DC $143000 ;2.52 |I|=5
DC $175000 ;2.91 |I|=6
DC $1A9000 ;3.32 |I|=7
; WIBASE
DC $FF4000 ;-0.75 |I|=0
DC $012000 ;1.13 |I|=1
DC $029000 ;2.56 |I|=2
DC $040000 ;4.00 |I|=3
DC $070000 ;7.00 |I|=4
DC $0C6000 ;12.38 |I|=5
DC $163000 ;22.19 |I|=6
DC $462000 ;70.13 |I|=7
; FIBASE
DC $000000 ;0 |I|=0
DC $000000 ;0 |I|=1
DC $000000 ;0 |I|=2
DC $100000 ;1 |I|=3
DC $100000 ;1 |I|=4
DC $100000 ;1 |I|=5
DC $300000 ;3 |I|=6
DC $700000 ;7 |I|=7
; TAB
DC $1E0000
DC $3E0000
DC $5E0000
DC $7E0000
DC $9E0000
DC $BE0000
DC $DE0000
DC $FE0000
; RSHFT
DC $800000
DC $400000 ;>>1 <<23
DC $200000 ;>>2 <<22
DC $100000 ;>>3 <<21
DC $080000 ;>>4 <<20
DC $040000 ;>>5 <<19
DC $020000 ;>>6 <<18
DC $010000 ;>>7 <<17
DC $008000 ;>>8 <<16
DC $004000 ;>>9 <<15
DC $002000 ;>>10 <<14
DC $001000 ;>>11 <<13
DC $000800 ;>>12 <<12
DC $000400 ;>>13 <<11
DC $000200 ;>>14 <<10
DC $000100 ;>>15 <<9
DC $000080 ;>>16 <<8
DC $000040 ;>>17 <<7
DC $000020 ;>>18 <<6
DC $000010 ;>>19 <<5
DC $000008 ;>>20 <<4
DC $000004 ;>>21 <<3
DC $000002 ;>>22 <<2
DC $000001 ;>>23 <<1